package jp.sourceforge.akjrcp.videotools;

import com.akjava.lib.standards.process.ProcessPrinter;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.commons.ui.FileDirChoicer;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeEvent;
import jp.sourceforge.akjrcp.commons.ui.AbstractFileDirChoicer.FileStatusChangeListener;
import jp.sourceforge.akjrcp.commons.ui.widget.WidgetBuilder;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegCommandUtil;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUI;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.ffmpeg.SimpleCommandExecuter;
import jp.sourceforge.akjrcp.ui.param.ParamBoolean;
import jp.sourceforge.akjrcp.ui.param.ParamRadioGroup;
import jp.sourceforge.akjrcp.ui.param.ParamText;
import jp.sourceforge.akjrcp.ui.param.ParamTextArea;
import jp.sourceforge.akjrcp.util.ExecutingControler;
import jp.sourceforge.akjrcp.util.FileNameUtils;
import jp.sourceforge.akjrcp.util.StatusBarUtils;
import jp.sourceforge.akjrcp.util.ExecutingControler.ExecutingControlButton;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class MplexViewer extends ViewPart {
	public static Log log=LogFactory.getLog(MplexViewer.class);
	
	public static final String ID = MplexViewer.class.getName();
	
	private ParamBoolean vbr;
	private ParamRadioGroup format;

	
	private FileDirChoicer inputVideoFileChooser;
	private FileDirChoicer inputAudioFile1Chooser;
	private FileDirChoicer inputAudioFile2Chooser;
	private FileDirChoicer outputFileChooser;
	private MplexExecute mplexExecute;

	private Text syncText;
	

	public class AudoFileSet implements FileStatusChangeListener{

		public void addList(FileStatusChangeEvent event) {
			String path=event.getFilePath();
			if(!path.equals("")){
				//set audio
				String extensions[]={"ac3","mp2","m2a","lpcm"};
				for (int i = 0; i < extensions.length; i++) {
					String audioPath=FileNameUtils.getChangedExtensionName(new File(path), extensions[i], true);
					if(new File(audioPath).exists()){
						inputAudioFile1Chooser.setFilePath(audioPath);
						break;
					}
				}
				String exportPath=FileNameUtils.getChangedExtensionName(new File(path), "vob");
				if(!new File(exportPath).exists()){
					outputFileChooser.setFilePath(exportPath);
				}
			}
			mplexExecute.updateControlSwitch();
		}

		public void removeList(FileStatusChangeEvent event) {
			// TODO Auto-generated method stub
			
		}

	
		
	}
	public void createPartControl(Composite parent) {
		mplexExecute = new MplexExecute();
		
		parent.setLayout(new GridLayout(1,false));
		
		
		
		
		FileSelected selectedListener=new FileSelected();
		inputVideoFileChooser = new FileDirChoicer(parent,SWT.BORDER,FileDirChoicer.FILE,Messages.getString("videotool.mplex_video"));
		inputVideoFileChooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		inputVideoFileChooser.addFileListChangeListener(selectedListener);
		inputVideoFileChooser.setFilterExtensions(new String[]{"*.m2v;*.m1v"});
		inputVideoFileChooser.addFileListChangeListener(new AudoFileSet());
		
		inputAudioFile1Chooser = new FileDirChoicer(parent,SWT.BORDER,FileDirChoicer.FILE,Messages.getString("videotool.mplex_audio1"),true);
		inputAudioFile1Chooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		inputAudioFile1Chooser.addFileListChangeListener(selectedListener);
		inputAudioFile1Chooser.setFilterExtensions(new String[]{"*.mp2;*.m2a;*.ac3;*.lpcm"});
		
		inputAudioFile2Chooser = new FileDirChoicer(parent,SWT.BORDER,FileDirChoicer.FILE,Messages.getString("videotool.mplex_audio1"),true);
		inputAudioFile2Chooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		inputAudioFile2Chooser.addFileListChangeListener(selectedListener);
		inputAudioFile2Chooser.setFilterExtensions(new String[]{"*.mp2;*.m2a;*.ac3;*.lpcm"});
		
		
		
		
		
		
		Composite s2=createSplitComposite(parent,1,false,new GridData(GridData.FILL_HORIZONTAL));
		
		format=new ParamRadioGroup(s2,SWT.NONE,"f","format",new String[]{"0","1","2","3","4","5","6","7","8","9","10","11"},new String[]{"Generic MPEG1(0)","VCD(1)","user-rate VCD(2)","Generic MPEG2(3)","SVCD(4)","user-rate SVCD(5)","CD Stills(6)","SVCD Stills(7)","DVD with NAV sectors(8)"," DVD(9)",Messages.getString("mpexviewr.mpeg_ts10")," MPEG-PS(11)FFMpeg"},5);
		format.setValue("8");//-f 8 is default
		
		Label label=WidgetBuilder.createLabel(s2, Messages.getString("mpexviewr.mpeg_ts_info"));
		
		vbr=new ParamBoolean(s2,SWT.NONE,"V","vbr");
		
		outputFileChooser = new FileDirChoicer(parent,SWT.BORDER,FileDirChoicer.SAVE,Messages.getString("videotool.mplex_output"));
		outputFileChooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		outputFileChooser.setFilterExtensions(new String[]{"*.vob"});
		outputFileChooser.addFileListChangeListener(selectedListener);
		
		mplexExecute.addControl(inputVideoFileChooser);
		mplexExecute.addControl(outputFileChooser);
		mplexExecute.addControl(inputAudioFile1Chooser);
		mplexExecute.addControl(inputAudioFile2Chooser);
		mplexExecute.addControl(format);
		mplexExecute.addControl(vbr);
		
		//sync labels
		Composite syncOffset=new Composite(s2,SWT.NULL);
		syncOffset.setLayout(new GridLayout(3,false));
		Label synclabel=WidgetBuilder.createLabel(syncOffset, Messages.getString("mpexviewr.sync_offset"));
		syncText = WidgetBuilder.createBorderText(syncOffset, "");
		Label syncms=WidgetBuilder.createLabel(syncOffset, "ms");
		
		
		
		ExecutingControlButton exec=new ExecutingControlButton(parent,SWT.NULL,mplexExecute,
				Messages.getString("videotool.mplex_mux"),Messages.getString("cancel"));
		
	
	}
	
	public void setFocus() {
		
	}
	private Composite createSplitComposite(Composite parent,int split,boolean same,Object data){
		Composite composite=new Composite(parent,SWT.NULL);
		composite.setLayout(new GridLayout(split,same));
		if(data!=null){
			composite.setLayoutData(data);
		}
		return composite;
	}
	private ParamTextArea createGridTextAreaGroup(Composite parent,String key,String label,Object data){
		/*Group group=new Group(parent,SWT.NULL);
		group.setText(label);
		group.setLayout(new FillLayout());
		group.setLayoutData(data);
		Text text=new Text(group,SWT.MULTI|SWT.V_SCROLL|SWT.H_SCROLL|SWT.BORDER);
		*/
		
		ParamTextArea text=new ParamTextArea(parent,SWT.NULL,key,label,ParamText.LAYOUT_FILL_BOTH);
		text.setLayoutData(data);
		return text;
	}
	
	private ParamText createLabeldText(Composite parent,String key,String label,Object data){
		ParamText text=new ParamText(parent,SWT.NULL,key,label,ParamText.LAYOUT_FILL_HORIZONTAL);
		if(data!=null){
			text.setLayoutData(data);
		}
		return text;
	}
	
	public class MplexExecute extends ExecutingControler{
		
		
		private String inputVideoFileChooser_value;
		private String inputAudioFile1Chooser_value;
		private String inputAudioFile2Chooser_value;

		private String outputFileChooser_value;
		
		
		private boolean vbr_value;
		private String format_value;
		private String result_message="";
		
		private int sync_value;
		public void afterExecute() {
			
		}

		@Override
		public void beforeExecute() {
			vbr_value=vbr.getBoolean();
			format_value=format.getValue();
			
			inputVideoFileChooser_value=inputVideoFileChooser.getAbsoluteFilePath();
			outputFileChooser_value=outputFileChooser.getAbsoluteFilePath();
			inputAudioFile1Chooser_value=inputAudioFile1Chooser.getAbsoluteFilePath();
			inputAudioFile2Chooser_value=inputAudioFile2Chooser.getAbsoluteFilePath();
			
			if(syncText.getText().length()>0){
				try{
			sync_value=Integer.parseInt(syncText.getText());
				}catch(Exception e){}
			}
		}

		@Override
		public boolean canExecute() {
			if( !inputVideoFileChooser.getAbsoluteFilePath().equals("") &&!outputFileChooser.getAbsoluteFilePath().equals("") ){
				return !inputAudioFile1Chooser.getAbsoluteFilePath().equals("") ||!inputAudioFile2Chooser.getAbsoluteFilePath().equals("");
			}
			return false;
			
		}

		@Override
		public void cancelExecuting() {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void inExecute() {
			String mplexPath=Akj_betasPlugin.getDefault().getPreferenceStore().getString(VideoToolsSettingPage.PATH_MPLEX);
			if(mplexPath.equals("")){
				StatusBarUtils.showStatusBar(Messages.getString("videotool.mplex_no_mplex"));
				return;
			}
			if(format_value.equals("10")||format_value.equals("11")){//muxing mpeg ts vis ffmpeg
				String ffmpegExe=FFMpegUI.getFFmpegOrPureFFMpeg();
				List<String> inputList=new ArrayList<String>();
				
				inputList.add(inputVideoFileChooser_value);
				
				
				if(!inputAudioFile1Chooser_value.equals("")){
					inputList.add(inputAudioFile1Chooser_value);
				}
				
				if(!inputAudioFile2Chooser_value.equals("")){
					inputList.add(inputAudioFile2Chooser_value);
				}
				String ffroamt="mpegts";
				if(format_value.equals("11")){
					ffroamt="vob";
				}
				String commands[]=FFMpegCommandUtil.copyInputsCommand(ffmpegExe,inputList.toArray(new String[inputList.size()]),ffroamt,outputFileChooser_value);
				FFMpegUtils.toPrintCommand(commands);
				Akj_betasPlugin.getDefault().getProcessPrinter().printOutput("####\n");
				Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(FFMpegUtils.toPrintCommand(commands)+"\n");
				SimpleCommandExecuter executer=new SimpleCommandExecuter(commands);
				MplexProcessPrinter printer=new MplexProcessPrinter();
				executer.setPrinter(printer);
				StatusBarUtils.showStatusBar(Messages.getString("mplexviewer.ffmpeg_start"));
				executer.execute();
				StatusBarUtils.showStatusBar(printer.getResult());
				}else{
			List<String> list=new ArrayList<String>();
			
			list.add(mplexPath);
			list.add("-f");
			list.add(format_value);
			if(vbr_value){
				list.add("-V");//vbr
			}
			
			if(sync_value!=0){
				list.add("-O");
				list.add(""+sync_value+"ms");
			}
			
			list.add("-o");
			list.add(outputFileChooser_value);
			list.add(inputVideoFileChooser_value);
			
			
			if(!inputAudioFile1Chooser_value.equals("")){
				list.add(inputAudioFile1Chooser_value);
			}
			
			if(!inputAudioFile2Chooser_value.equals("")){
				list.add(inputAudioFile2Chooser_value);
			}
			String commands[]=list.toArray(new String[list.size()]);
			FFMpegUtils.toPrintCommand(commands);
			Akj_betasPlugin.getDefault().getProcessPrinter().printOutput("####\n");
			Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(FFMpegUtils.toPrintCommand(commands)+"\n");
			SimpleCommandExecuter executer=new SimpleCommandExecuter(commands);
			MplexProcessPrinter printer=new MplexProcessPrinter();
			executer.setPrinter(printer);
			StatusBarUtils.showStatusBar(Messages.getString("mplexviewer.mplex_start"));
			
			
			executer.execute();
			
			StatusBarUtils.showStatusBar(printer.getResult());
			
			}
		}
		
		
	}
	public class MplexProcessPrinter implements ProcessPrinter{
		private String result="";
		public void printError(String error) throws IOException {
			print(error);
		}
		
		public void print(String text){
			Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(text);
			if(text.indexOf("**ERROR: [???] Too many frame drops -exiting")!=-1){
				result=Messages.getString("mplexviewer.faild");
			}
		}

		public void printOutput(String output) throws IOException {
			print(output);
		}

		public String getResult() {
			return result;
		}

		public void setResult(String result) {
			this.result = result;
		}
	}

	public class FileSelected implements FileStatusChangeListener{

		public void addList(FileStatusChangeEvent event) {
			
			mplexExecute.updateControlSwitch();
		}

		public void removeList(FileStatusChangeEvent event) {
			mplexExecute.updateControlSwitch();
		}
		
	}

	
		
}